package com.zz.controller;

import com.zz.domain.StudentMachine;
import com.zz.feign.ExamService;
import com.zz.service.StudentMachineService;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@RestController
public class DownstreamController {

    private static final Logger logger = LoggerFactory.getLogger(DownstreamController.class);
    @Autowired
    ExamService examService;
    @Autowired
    private StudentMachineService studentMachineService;

    @Value("${submission.file.path}")
    private String uploadDir;

    private static final long MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB

    @PostMapping("/process-file")
    public String processFile(@RequestParam("cocosConfigFile") MultipartFile file) {
        if (file == null || file.isEmpty()) {
            logger.error("上传文件为空或未提供文件");
            return "文件为空，请重新上传";
        }

        // 1. 检查文件大小
        if (file.getSize() > MAX_FILE_SIZE) {
            logger.error("文件大小超过限制: {} bytes (最大允许 {} bytes)", file.getSize(), MAX_FILE_SIZE);
            return "文件大小超过10MB限制";
        }

        String originalFilename = file.getOriginalFilename();
        logger.info("开始处理文件: {}", originalFilename);

        try {
            // 2. 从文件名中提取考号
            String examNumber = extractExamNumber(originalFilename);
            if (examNumber == null || examNumber.isEmpty()) {
                logger.error("无法从文件名中提取考号: {}", originalFilename);
                return "文件名格式不正确，无法提取考号";
            }
            logger.info("提取到考号: {}", examNumber);

            // 3. 查询学生机器信息
            StudentMachine machine = studentMachineService.getMachineByExamNumber(examNumber);
            if (machine == null) {
                logger.error("未找到考号对应的学生机器: {}", examNumber);
                return "未找到考号为 " + examNumber + " 的学生机器信息";
            }
            logger.info("找到学生信息: {} ({})", machine.getName(), machine.getExamnumber());

            // 4. 检查机器状态
            if (!"online".equals(machine.getStatus())) {
                logger.error("学生机器不在线: 当前状态 {}", machine.getStatus());
                return "学生机器不在线，无法接收文件";
            }

            // 5. 准备上传目录（使用配置的路径）
            Path uploadPath = Paths.get(uploadDir).toAbsolutePath().normalize();
            logger.info("准备保存到目录: {}", uploadPath);

            if (!Files.exists(uploadPath)) {
                try {
                    Files.createDirectories(uploadPath);
                    logger.info("创建目录成功");
                } catch (IOException e) {
                    logger.error("无法创建上传目录", e);
                    return "无法创建上传目录: " + e.getMessage();
                }
            }

            // 6. 生成压缩文件名（包含学生姓名、考号和时间戳）
            String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
            String zipFilename = String.format("%s_%s_%s.zip",
                    machine.getExamnumber(),
                    machine.getName(),
                    timestamp);
            logger.info("压缩文件名: {}", zipFilename);

            // 7. 直接创建压缩文件，不保存原始文件
            Path zipFilePath = uploadPath.resolve(zipFilename);
            try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath.toFile()))) {
                ZipEntry zipEntry = new ZipEntry(originalFilename);
                zipOut.putNextEntry(zipEntry);
                zipOut.write(file.getBytes());
                zipOut.closeEntry();
                logger.info("压缩文件创建成功: {}", zipFilePath);

                // 创建MultipartFile从zip文件
                File zipFile = zipFilePath.toFile();
                FileItem fileItem = new DiskFileItem(
                        "file",
                        Files.probeContentType(zipFilePath),
                        false,
                        zipFile.getName(),
                        (int) zipFile.length(),
                        zipFile.getParentFile());

                try (InputStream input = new FileInputStream(zipFile)) {
                    OutputStream os = fileItem.getOutputStream();
                    IOUtils.copy(input, os);
                }

                MultipartFile multipartFile = new CommonsMultipartFile(fileItem);

                // 转发压缩后的文件
                String result = examService.forwardFile(multipartFile);
                logger.info("文件转发结果: {}", result);

            } catch (IOException e) {
                logger.error("创建压缩文件失败", e);
                return "创建压缩文件失败: " + e.getMessage();
            }

            // 8. 更新学生状态
            try {
                studentMachineService.updateStudentStatus(machine.getMachineId(), "submitted");
                logger.info("学生状态更新为 submitted");
            } catch (Exception e) {
                logger.error("更新学生状态失败", e);
                // 不返回错误，因为文件已成功保存
            }

            return String.format("文件处理成功！考生: %s(%s), 保存路径: %s",
                    machine.getName(), machine.getExamnumber(), zipFilePath.getFileName());

        } catch (Exception e) {
            logger.error("文件处理过程中发生错误", e);
            return "文件处理失败: " + e.getMessage();
        }
    }

    /**
     * 增强版考号提取方法，支持EXAM-XXX格式
     */
    private String extractExamNumber(String filename) {
        if (filename == null || filename.isEmpty()) {
            return null;
        }

        // 处理中文括号和空格情况
        filename = filename.replaceAll("（", "(").replaceAll("）", ")").trim();

        // 去除路径和扩展名
        String basename = new File(filename).getName();
        int dotIndex = basename.lastIndexOf('.');
        if (dotIndex > 0) {
            basename = basename.substring(0, dotIndex);
        }

        // 优先匹配EXAM-开头的考号格式（例如EXAM-9760）
        Pattern examPattern = Pattern.compile("EXAM-\\d+");
        Matcher examMatcher = examPattern.matcher(basename);
        if (examMatcher.find()) {
            return examMatcher.group();
        }

        // 如果没有找到EXAM-格式，尝试其他分割方式
        String[] possibleSplitters = {"_", " ", "(", ")"}; // 移除"-"作为分割符，避免拆分考号
        String[] parts = {basename};
        for (String splitter : possibleSplitters) {
            if (basename.contains(splitter)) {
                parts = basename.split(splitter);
                break;
            }
        }

        // 智能识别考号（最长数字串）
        String candidate = "";
        for (String part : parts) {
            String trimmed = part.trim();
            // 匹配学号规则：至少6位数字
            if (trimmed.matches("\\d{6,}") && trimmed.length() > candidate.length()) {
                candidate = trimmed;
            }
        }
        return candidate.isEmpty() ? parts[0].trim() : candidate;
    }
}